package org.devbg.academy.corejava.shop.db.utils;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public final class HibernateSessionManager {
	/**
	 * Hides default constructor for this utility class.
	 */
	private HibernateSessionManager() {
	}

	// Explicit volatile definitions
	private static volatile SessionFactory sessionFactory = null;
	private static Session session = null;

	/**
	 * Starts a new session and stores it in the context of the current thread.
	 */
	public static Session openSession() {
		// Start new Hibernate session
		SessionFactory sessionFactory = getSessionFactory();
		Session hbSession = sessionFactory.openSession();

		// Start new transaction for the session
		hbSession.beginTransaction();

		// Save the session in the context of the current thread
		session = hbSession;

		return hbSession;
	}

	/**
	 * Gets the currently active Hibernate session (for the current thread).
	 * Returns null if the current thread do not have an active session.
	 */
	public static Session getCurrentSession() {
		return session;
	}

	/**
	 * Commits the active transaction and immediately starts a new one. The
	 * session remains active.
	 */
	public static void commitTransaction() {
		Session hbSession = getCurrentSession();
		if ((hbSession != null) && (hbSession.isOpen())) {
			Transaction tran = hbSession.getTransaction();
			if (tran.isActive()) {
				tran.commit();
				hbSession.beginTransaction();
			}
		}
	}

	/**
	 * Rollbacks the active transaction, closes the active sesion (because it's
	 * state is invalid) and starts a new session and transaction.
	 */
	public static void rollbackTransaction() {
		Session hbSession = getCurrentSession();
		// Rollback the active transaction
		try {
			if ((hbSession != null) && (hbSession.isOpen())) {
				Transaction tran = hbSession.getTransaction();
				if (tran.isActive()) {
					tran.rollback();
				}
			}
		} finally {
			// Close the active session. It's state is invalid
			closeSession();
		}
	}

	public static void closeSession() {
		Session hbSession = getCurrentSession();
		if ((hbSession != null) && (hbSession.isOpen())) {
			hbSession.close();
		}
		session = null;
	}

	/**
	 * Create a single instance of the session factory (on demand). Implements
	 * the classical thread-safe singleton pattern with volatile static member
	 * holding the instance (see
	 * http://en.wikipedia.org/wiki/Singleton_pattern#Java).
	 */
	private static SessionFactory getSessionFactory() {
		if (sessionFactory == null) {
			synchronized (HibernateSessionManager.class) {
				if (sessionFactory == null) {
					// Load the Hibernate settings from hibernate.cfg.xml
					Configuration cfg = new Configuration();
					cfg.configure();
					// Create the Hibernate SessionFactory instance
					sessionFactory = cfg.buildSessionFactory();
				}
			}
		}
		return sessionFactory;
	}

}
